/*
 * Copyright (C) 2012 The Android Open Source Project 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at 
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 */

package com.example.google.tv.picasanotifier;

import com.example.google.tv.picasanotifier.model.PhotoData;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.PowerManager;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.Toast;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;

/**
 * Activity which allows the user to play slideshow of photos.
 */
public class SlideShowActivity extends Activity implements Animation.AnimationListener {
    
    private static final String TAG = "SlideShowActivity";

    private ImageView[] mImage = new ImageView[2];

    private Bitmap mBitmap;

    private static int mCount, mPos;

    private ArrayList<PhotoData> mPhotoData;

    private boolean mPlaying;

    private Toast mToast;

    private ProgressBar mProgressBar;

    private PowerManager.WakeLock mWakeLock;

    private PowerManager mPowerManager;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.view_photo);

        // Make the screen be always on until the SlideshowActivity gets paused.
        mPowerManager = (PowerManager)getSystemService(Context.POWER_SERVICE);
        mWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "DoNotDimScreen");

        mImage[0] = (ImageView)findViewById(R.id.image_1);
        mImage[1] = (ImageView)findViewById(R.id.image_2);
        mProgressBar = (ProgressBar)findViewById(R.id.progress_bar);
        mToast = Toast.makeText(this, "", Toast.LENGTH_LONG);
        Bundle extras = getIntent().getExtras();
        if (extras != null) {
            mPos = extras.getInt("pos");
            mCount = mPos;
            mPhotoData = extras.getParcelableArrayList("photos");
        }
        showImage(mImage[0], mPos);
        if (mPhotoData.size() > 1) {
            showImage(mImage[1], mPos++);
            mImage[1].setVisibility(View.INVISIBLE);
            showToast(R.string.slideshow_play);
        }
    }

    /**
     * Show the image in full-screen.
     * 
     * @param view The ImageView to display the photo
     * @param pos The index of the selected photo
     */
    public void showImage(ImageView view, int pos) {

        /**
         * Get the image in a separate non-UI thread
         */
        class ViewImageTask extends AsyncTask<Object, Void, Bitmap> {
            private ImageView view;

            private Drawable d;

            private InputStream is;

            private int pos;

            @Override
            protected Bitmap doInBackground(Object... params) {
                view = (ImageView)params[0];
                pos = (Integer)params[1];
                try {
                    is = (InputStream)fetch(mPhotoData.get(pos).getPhotoFullUrl());    
                } catch (MalformedURLException e) {
                    Log.e(TAG, "Could not be parsed as a URL "+ mPhotoData.get(pos).getPhotoFullUrl());
                } catch (IOException e) {
                    Log.e(TAG, "Could not obtain the content");
                }
                d = Drawable.createFromStream(is, "src");
                mBitmap = ((BitmapDrawable)d).getBitmap();
                return mBitmap;
            }

            @Override
            protected void onProgressUpdate(Void... values) {
                super.onProgressUpdate(values);
                mProgressBar.setVisibility(View.VISIBLE);
            }

            @Override
            protected void onPostExecute(Bitmap result) {
                view.setImageBitmap(result);
                view.requestFocus();
                super.onPostExecute(result);
                mProgressBar.setVisibility(View.INVISIBLE);
            }
        }
        new ViewImageTask().execute(view, pos);
    }

    /**
     * Fetch the given url
     * 
     * @param address The path of the url
     * @return The content of the url
     * @throws MalformedURLException
     * @throws IOException
     */
    public Object fetch(String address) throws MalformedURLException, IOException {
        URL url = new URL(address);
        Object content = url.getContent();
        return content;
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {

        switch (keyCode) {
            case KeyEvent.KEYCODE_DPAD_LEFT: {
                mCount--;
                if (mCount < 0) {
                    mCount = mPhotoData.size() - 1;
                }
                showImage(mImage[0], mCount);
                break;
            }
            case KeyEvent.KEYCODE_DPAD_RIGHT: {
                mCount++;
                if (mCount >= mPhotoData.size()) {
                    mCount = 0;
                }
                showImage(mImage[0], mCount);
                break;
            }
            case KeyEvent.KEYCODE_MEDIA_PLAY: {
                if (!mPlaying) {
                    if (mPhotoData.size() > 1) {
                        beginSlideShow();
                    }
                }
                mPlaying = true;
                break;
            }
            case KeyEvent.KEYCODE_MEDIA_PAUSE: {
                mPlaying = false;
                showToast(R.string.slideshow_paused);
                break;
            }
        }
        return super.onKeyDown(keyCode, event);
    }

    /**
     * Show hint to start the slideshow
     * 
     * @param slideshow
     */
    private void showToast(int slideshow) {
        mToast.setText(slideshow);
        mToast.show();
    }

    /**
     * Start the slideshow of photos and notify the user that slideshow has been
     * started
     */
    private void beginSlideShow() {
        mPlaying = true;
        showToast(R.string.slideshow_started);
        playAnim();
    }

  
    /**
     * Show fade-in and fade-out animation
     */
    private void playAnim() {
        // Hold the source and destination of the transition
        ImageView mFromImage, mToImage;
        mFromImage = mImage[mPos & 1];
        mToImage = mImage[(mPos + 1) & 1];
        mFromImage.setVisibility(View.VISIBLE);
       
        // Animation useful for fading things in and out.
        // 1.0 means fully opaque and 0.0 means fully transparent.
        AlphaAnimation mFadeOutAnimation = new AlphaAnimation(1.0f, 0.0f);
        mFadeOutAnimation.setStartOffset(3000);
        mFadeOutAnimation.setDuration(3000);
        mFadeOutAnimation.setFillAfter(false);
        mFadeOutAnimation.setInterpolator(new LinearInterpolator());
        if (mPlaying) {
            mFromImage.startAnimation(mFadeOutAnimation);
        }

        AlphaAnimation mFadeInAnimation = new AlphaAnimation(0.0f, 1.0f);
        mFadeInAnimation.setStartOffset(3000);
        mFadeInAnimation.setDuration(3000);
        mFadeInAnimation.setAnimationListener(this);
        mFadeInAnimation.setInterpolator(new LinearInterpolator());
        if (mPlaying) {
            mToImage.startAnimation(mFadeInAnimation);
        }
        
    }

    @Override
    public void onAnimationEnd(Animation animation) {
        // Show the next image when animation ends and notify the listener.
        int pos = mPos++ % (mPhotoData.size());
        int imageIndex = (mPos + 1) & 1;
        showImage(mImage[imageIndex], pos);
        mImage[imageIndex].setVisibility(View.INVISIBLE);
        this.playAnim();
    }

    @Override
    public void onAnimationRepeat(Animation animation) {
    }

    @Override
    public void onAnimationStart(Animation animation) {
    }

    @Override
    protected void onPause() {
        super.onPause();
        mWakeLock.release();
    }

    @Override
    protected void onResume() {
        super.onResume();
        mWakeLock.acquire();
    }
}
